package com.bilibili.magicasakurademo.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.AbsButton;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentState;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.InputAttribute;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Switch;
import ohos.agp.components.Text;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.multimodalinput.event.TouchEvent;
import ohos.utils.IntentConstants;
import ohos.utils.net.Uri;

import com.bilibili.magicasakura.utils.ThemeUtils;
import com.bilibili.magicasakura.widgets.TintButton;
import com.bilibili.magicasakura.widgets.TintEditText;
import com.bilibili.magicasakura.widgets.TintImageView;
import com.bilibili.magicasakura.widgets.TintTextView;
import com.bilibili.magicasakurademo.ResourceTable;
import com.bilibili.magicasakurademo.slice.dialog.CardPickerDialog;
import com.bilibili.magicasakurademo.slice.dialog.ProgressCheckDialog;
import com.bilibili.magicasakurademo.slice.dialog.ProgressStyleDialog;
import com.bilibili.magicasakurademo.slice.utils.SnackAnimationUtil;
import com.bilibili.magicasakurademo.slice.utils.ThemeHelper;

import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.Timer;
import java.util.TimerTask;

/**
 * MyApplication
 *
 * @since 2021-05-21
 */
public class MainAbilitySlice extends AbilitySlice {
    Context mContext;
    Component rootView;
    private final String[] sTitles = new String[]{"Label", "Login", "Choice"};
    private TintButton loginBtn;
    private boolean isNameEmpty = true;
    private boolean isPwdEmpty = true;
    private final int ra = 20;
    private final int delay = 3000;
    private final int index1 = 1;
    private final int index2 = 2;
    private final int index3 = 3;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        getWindow().setStatusBarColor(ThemeUtils.getColor(this,
            getColor(ResourceTable.Color_theme_color_primary_dark)));
        mContext = this;
        init();
    }

    /**
     * 初始化
     */
    public void init() {
        rootView = findComponentById(ResourceTable.Id_layout);
        Image dialogTheme = (Image) findComponentById(ResourceTable.Id_toolbar_dialog_theme);
        dialogTheme.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                showDialog();
            }
        });

        DirectionalLayout listContainer = (DirectionalLayout) findComponentById(ResourceTable.Id_recycler);
        listContainer.addComponent(createHeaderComponent(this, index1));
        listContainer.addComponent(createLabelComponent(this));
        listContainer.addComponent(createHeaderComponent(this, index2));
        listContainer.addComponent(createLoginComponent(this));
        listContainer.addComponent(createHeaderComponent(this, index3));
        listContainer.addComponent(createChoiceComponent(this));
    }

    private void showDialog() {
        CardPickerDialog dialog = new CardPickerDialog(getContext());
        dialog.setClickListener(new CardPickerDialog.ClickListener() {
            @Override
            public void onConfirm(int currentTheme) {
                if (ThemeHelper.getTheme(mContext) != currentTheme) {
                    changeTheme(currentTheme);

                    final int duration = 250;
                    final int delayTime = 1000;
                    AnimatorProperty animatorIn = new AnimatorProperty();
                    AnimatorProperty animatorOut = new AnimatorProperty();
                    animatorIn.setDuration(duration).alphaFrom(0).alpha(1);
                    animatorOut.setDuration(duration).alphaFrom(1).alpha(0);
                    Component snackLayout = findComponentById(ResourceTable.Id_snack_layout);
                    if (snackLayout != null) {
                        Text textView = (Text) snackLayout.findComponentById(ResourceTable.Id_content);
                        textView.setText(getSnackContent(currentTheme));
                        SnackAnimationUtil.with(animatorIn, animatorOut)
                            .setDismissDelayTime(delayTime)
                            .setTarget(snackLayout)
                            .play();
                    }
                }
            }
        });
        dialog.show();
    }

    private String getSnackContent(int current) {
        SecureRandom random = new SecureRandom();
        int resId = 0;
        switch (random.nextInt(index3)) {
            case 0:
                resId = ResourceTable.String_magicasrkura_prompt_0;
                break;
            case index1:
                resId = ResourceTable.String_magicasrkura_prompt_1;
                break;
            case index2:
                resId = ResourceTable.String_magicasrkura_prompt_2;
                break;
            default:
                break;
        }
        return getString(resId) + ThemeHelper.getName(current);
    }

    private void changeTheme(int currentTheme) {
        if (ThemeHelper.getTheme(this) != currentTheme) {
            ThemeHelper.setTheme(getContext(), currentTheme);
            ThemeUtils.refreshUI(getContext(), rootView);
            getWindow().setStatusBarColor(ThemeUtils.getColor(this,
                getColor(ResourceTable.Color_theme_color_primary_dark)));
            loginBtnCanEnable();
        }
    }

    private Component createHeaderComponent(Context context, int index) {
        Component mHeaderComponent = LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_layout_list_item_header, null, false);
        TintImageView icon = (TintImageView) mHeaderComponent.findComponentById(ResourceTable.Id_icon);
        Text title = (Text) mHeaderComponent.findComponentById(ResourceTable.Id_title);
        title.setText(sTitles[index - 1]);
        if (index == 1) {
            icon.setPixelMap(ResourceTable.Media_ic_looks_1);
        } else if (index == index2) {
            icon.setPixelMap(ResourceTable.Media_ic_looks_2);
        } else {
            icon.setPixelMap(ResourceTable.Media_ic_looks_3);
        }
        icon.setImageTintList(new Color(Color.getIntColor("#fb7299")));
        return mHeaderComponent;
    }

    private Component createLabelComponent(Context context) {
        Component mLabelComponent = LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_layout_list_item_label, null, false);
        TintTextView title = (TintTextView) mLabelComponent.findComponentById(ResourceTable.Id_title);
        Text content = (Text) mLabelComponent.findComponentById(ResourceTable.Id_prompt);
        AbsButton switchCompat = (Switch) mLabelComponent.findComponentById(ResourceTable.Id_switch_button);
        switchCompat.setCheckedStateChangedListener((absButton, isChecked) -> {
            if (isChecked) {
                StateElement selectorUnlock = new StateElement();
                PixelMapElement selectorUnlockPressed = new PixelMapElement(getPixelMapFromResource(getContext(),
                    ResourceTable.Media_ic_lock_white_24dp));
                PixelMapElement selectorUnlockEmpty = new PixelMapElement(getPixelMapFromResource(getContext(),
                    ResourceTable.Media_ic_lock_open_white_24dp));
                selectorUnlock.addState(new int[]{ComponentState.COMPONENT_STATE_PRESSED}, selectorUnlockPressed);
                selectorUnlock.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, selectorUnlockEmpty);
                title.setAroundElements(selectorUnlock, null, null, null);
                title.getmCompoundDrawableHelper().setTintColor(0, Color.getIntColor("#999999"),
                    getColor(ResourceTable.Color_theme_color_primary));
                title.getmCompoundDrawableHelper().setSkipNextApply(true);
                title.tint();
                content.setText(ResourceTable.String_textview_click_after);
            } else {
                StateElement selectorLock = new StateElement();
                PixelMapElement selectorLockPressed = new PixelMapElement(getPixelMapFromResource(getContext(),
                    ResourceTable.Media_ic_lock_open_white_24dp));
                PixelMapElement selectorLockEmpty = new PixelMapElement(getPixelMapFromResource(getContext(),
                    ResourceTable.Media_ic_lock_white_24dp));
                selectorLock.addState(new int[]{ComponentState.COMPONENT_STATE_PRESSED}, selectorLockPressed);
                selectorLock.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, selectorLockEmpty);
                title.setAroundElements(selectorLock, null, null, null);
                title.getmCompoundDrawableHelper().setTintColor(0,
                    getColor(ResourceTable.Color_theme_color_primary), Color.getIntColor("#999999"));
                title.getmCompoundDrawableHelper().setSkipNextApply(true);
                title.tint();
                content.setText(ResourceTable.String_textview_click_before);
            }
        });
        content.setClickedListener(component -> {
            if (switchCompat.isChecked()) {
                openUrl();
            }
        });
        return mLabelComponent;
    }

    private void openUrl() {
        String urlString = getString(ResourceTable.String_url_https);
        Intent intents = new Intent();
        Operation operation = new Intent.OperationBuilder()
            .withUri(Uri.parse(urlString))
            .withAction(IntentConstants.ACTION_SEARCH)
            .build();
        intents.setOperation(operation);
        mContext.startAbility(intents, 0);
    }

    private static PixelMap getPixelMapFromResource(Context context, int resourceId) {
        InputStream inputStream = null;
        ImageSource imageSource = null;
        ImageSource.DecodingOptions decodingOptions = null;
        try {
            // 创建图像数据源ImageSource对象
            inputStream = context.getResourceManager().getResource(resourceId);
            ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
            srcOpts.formatHint = "image/jpg";
            imageSource = ImageSource.create(inputStream, srcOpts);

            // 设置图片参数
            decodingOptions = new ImageSource.DecodingOptions();
            return imageSource.createPixelmap(decodingOptions);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private Component createLoginComponent(Context context) {
        Component mLoginComponent = LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_layout_list_item_login, null, false);
        TintEditText name = (TintEditText) mLoginComponent.findComponentById(ResourceTable.Id_username);
        final TintEditText password = (TintEditText) mLoginComponent.findComponentById(ResourceTable.Id_password);
        loginBtn = (TintButton) mLoginComponent.findComponentById(ResourceTable.Id_login_btn);
        initLoginBtn();
        name.setClickedListener(component -> {
            name.setBubbleSize(AttrHelper.vp2px(ra, mContext), AttrHelper.vp2px(ra, mContext));
            name.setBubbleElement(new ShapeElement(mContext, ResourceTable.Graphic_text_field_bubble));
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    name.setBubbleElement(new ShapeElement());
                    timer.cancel();
                }
            }, delay);
        });
        name.addTextObserver((s, i, i1, i2) -> {
            if (s.toCharArray().length != 0) {
                isNameEmpty = false;
            } else {
                isNameEmpty = true;
            }
            loginBtnCanEnable();
        });
        name.setInputMethodOption(InputAttribute.ENTER_KEY_TYPE_GO);
        password.addTextObserver((s, i, i1, i2) -> {
            if (s.toCharArray().length != 0) {
                isPwdEmpty = false;
            } else {
                isPwdEmpty = true;
            }
            loginBtnCanEnable();
        });
        password.setClickedListener(component -> {
            password.setBubbleSize(AttrHelper.vp2px(ra, mContext), AttrHelper.vp2px(ra, mContext));
            password.setBubbleElement(new ShapeElement(mContext, ResourceTable.Graphic_text_field_bubble));
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    password.setBubbleElement(new ShapeElement());
                }
            }, delay);
        });
        password.setInputMethodOption(InputAttribute.PATTERN_PASSWORD);
        return mLoginComponent;
    }

    private void initLoginBtn() {
        try {
            loginBtn.setBackgroundColor(mContext.getResourceManager()
                .getElement(ResourceTable.Color_theme_color_primary_trans).getColor());
            loginBtn.setTouchEventListener(new Component.TouchEventListener() {
                @Override
                public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                    if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
                        try {
                            loginBtn.setBackgroundColor(mContext.getResourceManager()
                                .getElement(ResourceTable.Color_theme_color_primary_dark).getColor());
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (NotExistException e) {
                            e.printStackTrace();
                        } catch (WrongTypeException e) {
                            e.printStackTrace();
                        }
                    } else if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                        loginBtnCanEnable();
                    }
                    return true;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        }
    }

    private void loginBtnCanEnable() {
        try {
            if (!isNameEmpty && !isPwdEmpty) {
                loginBtn.setEnabled(false);
                loginBtn.setBackgroundColor(mContext.getResourceManager()
                    .getElement(ResourceTable.Color_theme_color_primary).getColor());
            } else {
                loginBtn.setEnabled(false);
                loginBtn.setBackgroundColor(mContext.getResourceManager()
                    .getElement(ResourceTable.Color_theme_color_primary_trans).getColor());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        }
    }

    private Component createChoiceComponent(Context context) {
        Component mChoiceComponent = LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_layout_list_item_choice, null, false);
        Text textView1 = (Text) mChoiceComponent.findComponentById(ResourceTable.Id_progress_setting);
        Text textView2 = (Text) mChoiceComponent.findComponentById(ResourceTable.Id_download);
        textView1.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                new ProgressStyleDialog(context).show();
            }
        });
        textView2.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                new ProgressCheckDialog(context).show();
            }
        });
        return mChoiceComponent;
    }
}
